/**
 @file ctc_chip.h

 @author  Copyright (C) 2011 Centec Networks Inc.  All rights reserved.

 @date 2016-9-9

 @version v2.0

   This file contains all chip related data structure, enum, macro and proto.
*/

#ifndef _CTC_USW_CHIP_GLOBAL_H
#define _CTC_USW_CHIP_GLOBAL_H
#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/

#include "sal_types.h"
#include "ctc_mix.h"

/****************************************************************
*
* Defines and Macros
*
****************************************************************/
extern uint8 g_lchip_num;
extern uint8 g_ctcs_api_en;

struct sys_chip_info_s
{
    uint8 pp_base;          
    uint8  pp_num;             
    uint8 map_ldev;
    uint8 rsv;
};
typedef struct sys_chip_info_s sys_chip_info_t;
extern sys_chip_info_t sys_chip_info[CTC_MAX_LOCAL_CHIP_NUM_PP];

#define SYS_PP_BASE(lchip) sys_chip_info[lchip].pp_base
#define SYS_PP_NUM(lchip) sys_chip_info[lchip].pp_num
#define SYS_CORE_PP_BASE(lchip) sys_usw_vchip_get_core_pp_base(lchip)
#define SYS_CORE_PP_NUM(lchip) drv_vchip_get_core_pp_num(lchip)

#ifdef EMULATION_ENV
#define SYS_PP_BMP(lchip) sys_usw_vchip_get_pp_bmp(lchip)
#else
#define SYS_PP_BMP(lchip) ((1<<sys_chip_info[lchip].pp_num)-1)
#endif

#define SYS_LCHIP_CHECK_ACTIVE(lchip)                       \
    do {                                                    \
        if(0 != sys_usw_chip_check_active(lchip)){              \
            return CTC_E_INVALID_CHIP_ID; }            \
    } while (0)

#define SYS_LCHIP_CHECK_ACTIVE_IN_THREAD(lchip)             \
    do {                                                    \
        int32 (op) = 0;                                     \
        (op)=(sys_usw_chip_check_active(lchip));                \
        if ((op)<0)                                         \
        {                                                   \
            return;                                         \
        }                                                   \
    } while (0)

#define SYS_PP_BMP_MAPPING(ctc_pp_bmp)\
    (((ctc_pp_bmp) & SYS_PP_BMP(lchip)) ? ((ctc_pp_bmp) & SYS_PP_BMP(lchip)) : SYS_PP_BMP(lchip))

#define SYS_LCHIP_CHECK_ACTIVE_START_THREAD(lchip)          \
{                                                           \
    int32 (op) = 0;                                         \
    do {                                                    \
        (op)=(sys_usw_chip_check_active(lchip));            \
        if ((op)<0)                                         \
        {                                                   \
            sal_task_sleep(1000);                            \
        }                                                   \
    } while ((op)<0);                                       \
}

/*Below Define is for CTC APIs dispatch*/
/*---------------------------------------------------------------*/
#define LCHIP_CHECK(lchip)                                  \
    do {                                                    \
        if ((lchip) >= g_lchip_num){                        \
            return CTC_E_INVALID_CHIP_ID; }            \
    } while (0)

#define SYS_MAP_GPORT_TO_LCHIP(gport, lchip)                                    \
    do{                                                                         \
        uint8 gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport);\
        SYS_MAP_GCHIP_TO_LCHIP(gchip, lchip);   \
    }while(0);



/*from arctic use SYS_MAP_GPORT_TO_LCHIP1, lchip_base + lchip_id*/
#define SYS_MAP_GPORT_TO_LCHIP1(gport_tmp, lchip)                                           \
    do{                                                                                 \
        uint32 _tmp_id = 0;                                                              \
        uint8 _tmp_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(gport_tmp);                           \
        sys_usw_dmps_port_info_t dmps_port_info = {0};                                    \
        if (_tmp_gchip > CTC_MAX_GCHIP_CHIP_ID || (_tmp_gchip == CTC_LINKAGG_CHIPID))   \
        {                                                                               \
            return CTC_E_INVALID_CHIP_ID;                                               \
        }                                                                               \
        if(CTC_E_NONE != sys_usw_get_local_chip_id(_tmp_gchip, &lchip))                 \
        {                                                                               \
            return CTC_E_INVALID_CHIP_ID;                                               \
        }                                                                               \
        dmps_port_info.gport = gport_tmp;                                                    \
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &_tmp_id)); \
        if(_tmp_id >= SYS_PP_NUM(lchip)) return CTC_E_INVALID_PORT;  \
        lchip = SYS_PP_BASE(lchip) + _tmp_id;                             \
    }while(0);

#define CTC_SET_API_LCHIP(lchip, api_ldev)                 \
    do{                                                     \
        if(!g_ctcs_api_en) lchip = CTC_MAP_LCHIP(api_ldev); \
    }while(0);

#define CTC_FOREACH_LCHIP(lchip_start,lchip_end,all_lchip)  \
      if(g_ctcs_api_en && ((all_lchip) != 0xff))                                     \
      {                                                     \
          lchip_start = lchip;                              \
          lchip_end = lchip + 1;                            \
      }                                                     \
      else                                                  \
      {                                                     \
          lchip_start = all_lchip?0:lchip_start;            \
          if(DRV_FROM_AT(lchip)) {lchip_start = SYS_PP_BASE(lchip); lchip_end = lchip_start + 1;}\
          else{lchip_end = all_lchip?g_lchip_num:lchip_end;}      \
      }                                                     \
      for(lchip = lchip_start ; lchip < lchip_end; lchip++)

#define CTC_FOREACH_ROLLBACK(lchip_start,lchip_end)     \
      if(g_ctcs_api_en)                                 \
      {                                                 \
          lchip_start = 0;                              \
          lchip_end = 0;                                \
      }                                                 \
      else                                              \
      {                                                 \
         lchip_start = (lchip != lchip_end)? 0:lchip;   \
         lchip_end   = lchip;                           \
      }                                                 \
      for(lchip = lchip_start ; lchip < lchip_end; lchip++)

#define CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, all_lchip)  \
      lchip_start = all_lchip ? SYS_PP_BASE(lchip) : lchip_start;\
      lchip_end = all_lchip ? (lchip_start + SYS_PP_NUM(lchip)) : lchip_end;\
      for (lchip=lchip_start; lchip<lchip_end; lchip++)

#define CTC_AT_FOREACH_LCHIP2(lchip_start,lchip_end,all_lchip,feature)  \
    all_lchip = 1;                                         \
    if(!MCHIP_FEATURE_PP_EN(lchip, feature))               \
    {                                                      \
        all_lchip = 0;                                     \
        lchip_start = SYS_PP_BASE(lchip);  \
        lchip_end = lchip_start + 1;                       \
    }                                                      \
    CTC_AT_FOREACH_LCHIP(lchip_start, lchip_end, all_lchip)

#define CTC_MAP_GPORT_TO_PP_ID(gport_tmp, pp_id)    \
    if (CTC_IS_LINKAGG_PORT(gport_tmp)) {\
        (pp_id) = 0;\
    } else {\
        uint8 _lchip_ = 0;\
        sys_usw_dmps_port_info_t dmps_port_info = {0}; \
        dmps_port_info.gport = gport_tmp;\
        sys_usw_get_local_chip_id(CTC_MAP_GPORT_TO_GCHIP(gport_tmp), &_lchip_); \
        sys_usw_port_api_get_dmps_property(_lchip_, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &(pp_id)); \
    }

#define CTC_MAP_GPORT_TO_PP_BMP(gport_tmp, pp_bmp) \
    if (CTC_IS_LINKAGG_PORT(gport_tmp)) {\
        (pp_bmp) = 0x1; \
    } else {\
        uint8 _lchip_ = 0, gchip_id = 0; \
        uint32 _pp_id_ = 0; \
        sys_usw_dmps_port_info_t dmps_port_info = {0}; \
        gchip_id = CTC_MAP_GPORT_TO_GCHIP(gport_tmp); \
        if(CTC_E_NONE != sys_usw_get_local_chip_id(gchip_id, &_lchip_))                 \
        {                                                                               \
            return CTC_E_INVALID_CHIP_ID;                                               \
        }                                                                               \
        dmps_port_info.gport = gport_tmp; \
        ret = sys_usw_port_api_get_dmps_property(_lchip_, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PP_ID, &_pp_id_); \
        (pp_bmp) = (1<<_pp_id_); \
    }

#define SYS_MAP_CHANID_TO_PP_ID(lchip, rx, chan, pp_id) \
    if (chan >= MCHIP_CAP(SYS_CAP_PER_SLICE_CHANNEL_NUM)) {\
        return CTC_E_INVALID_PARAM;\
    } else { \
        sys_usw_port_api_get_sub_chan_by_chan(lchip, rx, chan, NULL, &pp_id, NULL); \
    }

#define CTC_AT_FOREACH_ROLLBACK(lchip_start,lchip_end) \
      lchip_start = (lchip != lchip_end)? lchip_start:lchip;   \
      lchip_end   = lchip;                           \
      for(lchip = lchip_start ; lchip < lchip_end; lchip++)
#define CTC_AT_FOREACH_CORE_LCHIP(lchip,pp_bmp,lchip_start,tmp_bmp) \
{ \
    if (!CTC_IS_BIT_SET(pp_bmp, lchip - lchip_start) || (CTC_IS_BIT_SET(tmp_bmp, SYS_CORE_PP_BASE(lchip) - SYS_PP_BASE(lchip)))) \
    { \
        continue; \
    } \
    CTC_BIT_SET(tmp_bmp, SYS_CORE_PP_BASE(lchip) - SYS_PP_BASE(lchip)); \
}

#define CTC_FOREACH_ERROR_RETURN(exist_ret,ret,op)     \
    {                                                  \
        int32 ret_tmp = CTC_E_NONE;                    \
        ret_tmp = (op);                                \
        if(exist_ret == ret_tmp)                       \
        {                                              \
            if(CTC_E_NONE == ret) {ret = ret_tmp;}     \
            continue;                                  \
        }                                              \
        else if(CTC_E_NONE == ret_tmp)                 \
        {                                              \
            continue;                                  \
        }                                              \
        else                                           \
        {                                              \
            ret = ret_tmp;                             \
            break;                                     \
        }                                              \
    }

#define CTC_AT_FOREACH_ERROR_RETURN(ret,op)     \
    {                                                  \
            int32 ret_tmp = CTC_E_NONE;                    \
            ret_tmp = (op);                                \
            if(CTC_E_NONE != ret_tmp)                 \
            {                                            \
                ret = ((ret_tmp&~CTC_ERROR_PPID_MASK) | ((lchip% SYS_PP_NUM(lchip)) << 20)); \
                break;\
            } \
        }

#define CTC_AT_FOREACH_ERROR_RETURN2(ret,op)           \
            {                                                  \
                int32 ret_tmp = CTC_E_NONE;                    \
                ret_tmp = (op);                                \
                if(CTC_E_NONE == ret_tmp || ret)                \
                {                                              \
                    continue;                                  \
                }                                              \
                else                                           \
                {                                              \
                    ret =  ((ret_tmp&~CTC_ERROR_PPID_MASK) | ((lchip% SYS_PP_NUM(lchip)) << 20)); \
                }                                              \
            }

#define CTC_FOREACH_ERROR_RETURN2(exist_ret1,exist_ret2,ret,op)     \
    {                                                               \
        int32 ret_tmp = CTC_E_NONE;                                 \
        ret_tmp = (op);                                             \
        if(g_lchip_num == 1 || g_ctcs_api_en)                        \
        {                                                           \
            ret = ret_tmp;                                          \
        }                                                           \
        else                                                        \
        {                                                           \
            if((exist_ret1 == ret_tmp) || (exist_ret2 == ret_tmp))  \
            {                                                       \
                if(++count == g_lchip_num)                          \
                {                                                   \
                    ret = ret_tmp;                                  \
                }                                                   \
                continue;                                           \
            }                                                       \
            else if(CTC_E_NONE == ret_tmp)                          \
            {                                                       \
                continue;                                           \
            }                                                       \
            else                                                    \
            {                                                       \
                ret = ret_tmp;                                      \
                break;                                              \
            }                                                       \
        }                                                           \
    }

#define CTC_ACL_SCL_FOREACH_ERROR_RETURN(exist_ret,ret,op)          \
    {                                                               \
        int32 ret_tmp = CTC_E_NONE;                                 \
        ret_tmp = (op);                                             \
        if(g_lchip_num == 1 || g_ctcs_api_en)                       \
        {                                                           \
            ret = ret_tmp;                                          \
        }                                                           \
        else                                                        \
        {                                                           \
            if(exist_ret == ret_tmp)                                \
            {                                                       \
                if(++count == g_lchip_num)                          \
                {                                                   \
                    ret = exist_ret;                                \
                }                                                   \
                continue;                                           \
            }                                                       \
            else if(CTC_E_NONE == ret_tmp)                          \
            {                                                       \
                continue;                                           \
            }                                                       \
            else                                                    \
            {                                                       \
                ret = ret_tmp;                                      \
                break;                                              \
            }                                                       \
        }                                                           \
    }

#define SYS_MAP_LCHIP(lchip, fea)   (MCHIP_FEATURE_PP_EN(lchip, fea)? lchip : SYS_PP_BASE(lchip))

/****************************************************************
*
* Data Structures
*
****************************************************************/

extern int32 sys_usw_chip_set_active(uint8 lchip, uint32 value);
extern int32 sys_usw_chip_check_active(uint8 lchip);
extern uint8
sys_usw_vchip_get_pp_base(uint8 lchip);
extern uint8
sys_usw_vchip_get_core_pp_base(uint8 lchip);
extern uint8
sys_usw_vchip_get_pp_num(uint8 lchip);
extern uint8
sys_usw_vchip_get_pp_bmp(uint8 lchip);
extern int32
sys_usw_port_api_get_sub_chan_by_chan(uint8 lchip, uint8 rx, uint16 chan, uint16 * sub_chan, uint8 * pp_id, uint8 * dp_id);

extern int32 sys_usw_chip_get_active_num(uint8* p_lchip_num);
/**@} end of @defgroup chip global  */

#ifdef __cplusplus
}
#endif

#endif

